using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace MonoCash
{
    public partial class Accounts : Form
    {

        public Accounts()
        {
            InitializeComponent();
            
            UpdateAccountControls();
            accountingCategoryBindingSource.DataSource = ObjectModel.AccountingCategory.AccountingCategories;
            accountTypeBindingSource.DataSource = ObjectModel.AccountType.AccountTypes;
        }


        private void TreeIterator(TreeNode n)
        {
            ObjectModel.Account thisAccount = new MonoCash.ObjectModel.Account(n.Name);
            int counter = 0;
            foreach (ObjectModel.Account a in thisAccount.ChildAccounts)
            {
                TreeNode child = new TreeNode();
                child.Name = a.ID.ToString();
                child.Text = a.Name;
                child.Tag = a;
                n.Nodes.Add(child);
                a.DisplayOrder = counter;
                counter++;
                TreeIterator(child);
            }
        }

        private string[] GetExpandedNodes(TreeNodeCollection t)
        {
            List<string> temp = new List<string>();
            foreach (TreeNode oldNode in t)
            {
                if (oldNode.IsExpanded)
                {
                    temp.Add(oldNode.Name);
                }
                if (oldNode.Nodes.Count > 0)
                {
                    temp.AddRange(GetExpandedNodes(oldNode.Nodes));
                }
            }
            return temp.ToArray();
        }

        private void UpdateAccountControls()
        {
            enableControls(false);

            //cboMoveDestination.DataSource = Program.AppSettings.Data.Accounts;
            //cboMoveDestination.DisplayMember = "LongName";
            //cboMoveDestination.ValueMember = "ID";

            ////BindingSource bs = new BindingSource(formBindingSource, "PossibleParentAccounts");
            ////cboParent.DataSource = Program.AppSettings.Data.Accounts;
            ////cboParent.DisplayMember = "LongName";
            ////cboParent.ValueMember = "ID";

            //cboCategory.DataSource = Program.AppSettings.Data.AccountingCategories;
            //cboCategory.DisplayMember = "Name";
            //cboCategory.ValueMember = "ID";

            //cboAccountType.DataSource = Program.AppSettings.Data.AccountTypes;
            //cboAccountType.DisplayMember = "Name";
            //cboAccountType.ValueMember = "ID";


            string[] expandedNodes = GetExpandedNodes(treeView1.Nodes);


            treeView1.Nodes.Clear();
            int counter = 0;
            foreach (ObjectModel.Account account in ObjectModel.Account.Accounts)
            {
                if (account.ParentAccountID == -1)
                {
                    TreeNode n = new TreeNode();
                    n.Name = account.ID.ToString();
                    n.Text = account.Name;
                    n.Tag = account;
                    treeView1.Nodes.Add(n);
                    TreeIterator(n);
                    account.DisplayOrder = counter;
                    counter++;
                }
            }

            foreach (string name in expandedNodes)
            {
                TreeNode[] result = treeView1.Nodes.Find(name, true);
                if (result.Length > 0)
                {
                    result[0].Expand();
                }
            }

        }
        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            formBindingSource.DataSource = e.Node.Tag;

            enableControls(false);
        }



        private void btnAddChildAccount_Click(object sender, EventArgs e)
        {

            ObjectModel.Account old = (ObjectModel.Account)formBindingSource.Current;
            ObjectModel.Account sub = new MonoCash.ObjectModel.Account();

            sub.Name = "Sub" + old.Name;
            sub.ParentAccountID = old.ID;
            sub.AccountingCategoryID = old.AccountingCategoryID;
            sub.AccountTypeID = old.AccountTypeID;
            sub.AllowTransactions = old.AllowTransactions;
            sub.IsVisible = old.IsVisible;

            UpdateAccountControls();
            try 
            {
                treeView1.SelectedNode = treeView1.Nodes.Find(sub.ID.ToString(), true)[0];
                enableControls(true);
            }
            catch {}
        } 




        private void btnSave_Click(object sender, EventArgs e)
        {
            if (btnSave.Text == "Save")
            {
                enableControls(false);

                UpdateAccountControls();
            }
            else
            {
                enableControls(true);
            }
            
        }
        private void enableControls(bool enabledValue)
        {
            btnSave.Text = "Edit";
            if (enabledValue)
            {
                
                btnSave.Text = "Save";
            }
            txtAccountName.Enabled = enabledValue;
            cboAccountType.Enabled = enabledValue;
            cboCategory.Enabled = enabledValue;
            cboParent.Enabled = enabledValue;
            chkAllowTransactions.Enabled = enabledValue;
            chkVisible.Enabled = enabledValue;

        }


        private void btnDelete_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("Are you sure? Any existing transactions will be moved to the default orphan account if they exist", "Delete Account", MessageBoxButtons.YesNoCancel) == DialogResult.Yes)
            {
                try
                {
                    ObjectModel.Account a = (ObjectModel.Account)formBindingSource.Current;
                    moveAccounts(a.ID, Convert.ToInt32(Program.AppSettings.UnbalancedTransactionsAccountID));
                    
                    a.Delete();
                    UpdateAccountControls();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Unable to delete account\n" + ex.Message);
                }
            }
        }
        private int moveAccounts(int source, int destination)
        {
            if (!Program.AppSettings.Data.AccountAllowsTransactions(destination))
            {
                throw new Exception("Account does not allow transactions");
            }
            ObjectModel.Account a = (ObjectModel.Account)formBindingSource.Current;

            int before = a.TransactionDetails.Count;
            foreach (ObjectModel.TransactionDetail t in a.TransactionDetails)
            {
                t.AccountID = destination;
            }

            int after = a.TransactionDetails.Count;

            if (after != 0)
            {
                throw new Exception("Unable to move all transactions");
            }
            return before;
        }
        private void btnMoveUp_Click(object sender, EventArgs e)
        {
            TreeNode n = treeView1.SelectedNode;
            if (n != null)
            {
                ObjectModel.Account current = (ObjectModel.Account)n.Tag;

                if (n.PrevNode != null)
                {
                    ObjectModel.Account previous = (ObjectModel.Account)n.PrevNode.Tag;
                    current.DisplayOrder = previous.DisplayOrder;
                    previous.DisplayOrder = previous.DisplayOrder - 1;
                }
                UpdateAccountControls();
                treeView1.SelectedNode = treeView1.Nodes.Find(current.ID.ToString(), true)[0];
            }
        }

        private void btnMoveDown_Click(object sender, EventArgs e)
        {
            TreeNode n = treeView1.SelectedNode;
            if (n != null)
            {
                ObjectModel.Account current = (ObjectModel.Account)n.Tag;

                if (n.NextNode != null)
                {
                    ObjectModel.Account next = (ObjectModel.Account)n.NextNode.Tag;
                    current.DisplayOrder = next.DisplayOrder;
                    next.DisplayOrder = next.DisplayOrder + 1;
                }
                UpdateAccountControls();
                treeView1.SelectedNode = treeView1.Nodes.Find(current.ID.ToString(), true)[0];
            }
            
        }

        private void btnMove_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("Are you sure you want to move transactions? This can not be undone! You should back up your data file prior to proceeding", "Are you sure?", MessageBoxButtons.YesNoCancel) == DialogResult.Yes)
            {
                try
                {
                    ObjectModel.Account a = (ObjectModel.Account)formBindingSource.Current;
                    MessageBox.Show("Success! " + moveAccounts(a.ID, Convert.ToInt32(cboMoveDestination.SelectedValue)).ToString() + " transactions were moved");
                }
                catch (Exception ex)
                {
                    MessageBox.Show("An error occurred\n" + ex.Message);
                }
            }
        }
    }
}